home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / WarpQuake / Src / sys_win.c < prev    next >
C/C++ Source or Header  |  2000-05-22  |  17KB  |  894 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // sys_win.c -- Win32 system interface code
  21.  
  22. #include "quakedef.h"
  23. #include "winquake.h"
  24. #include "errno.h"
  25. #include "resource.h"
  26. #include "conproc.h"
  27.  
  28. #define MINIMUM_WIN_MEMORY        0x0880000
  29. #define MAXIMUM_WIN_MEMORY        0x1000000
  30.  
  31. #define CONSOLE_ERROR_TIMEOUT    60.0    // # of seconds to wait on Sys_Error running
  32.                                         //  dedicated before exiting
  33. #define PAUSE_SLEEP        50                // sleep time on pause or minimization
  34. #define NOT_FOCUS_SLEEP    20                // sleep time when not focus
  35.  
  36. int            starttime;
  37. qboolean    ActiveApp, Minimized;
  38. qboolean    WinNT;
  39.  
  40. static double        pfreq;
  41. static double        curtime = 0.0;
  42. static double        lastcurtime = 0.0;
  43. static int            lowshift;
  44. qboolean            isDedicated;
  45. static qboolean        sc_return_on_enter = false;
  46. HANDLE                hinput, houtput;
  47.  
  48. static char            *tracking_tag = "Clams & Mooses";
  49.  
  50. static HANDLE    tevent;
  51. static HANDLE    hFile;
  52. static HANDLE    heventParent;
  53. static HANDLE    heventChild;
  54.  
  55. void MaskExceptions (void);
  56. void Sys_InitFloatTime (void);
  57. void Sys_PushFPCW_SetHigh (void);
  58. void Sys_PopFPCW (void);
  59.  
  60. volatile int                    sys_checksum;
  61.  
  62.  
  63. /*
  64. ================
  65. Sys_PageIn
  66. ================
  67. */
  68. void Sys_PageIn (void *ptr, int size)
  69. {
  70.     byte    *x;
  71.     int        j, m, n;
  72.  
  73. // touch all the memory to make sure it's there. The 16-page skip is to
  74. // keep Win 95 from thinking we're trying to page ourselves in (we are
  75. // doing that, of course, but there's no reason we shouldn't)
  76.     x = (byte *)ptr;
  77.  
  78.     for (n=0 ; n<4 ; n++)
  79.     {
  80.         for (m=0 ; m<(size - 16 * 0x1000) ; m += 4)
  81.         {
  82.             sys_checksum += *(int *)&x[m];
  83.             sys_checksum += *(int *)&x[m + 16 * 0x1000];
  84.         }
  85.     }
  86. }
  87.  
  88.  
  89. /*
  90. ===============================================================================
  91.  
  92. FILE IO
  93.  
  94. ===============================================================================
  95. */
  96.  
  97. #define    MAX_HANDLES        10
  98. FILE    *sys_handles[MAX_HANDLES];
  99.  
  100. int        findhandle (void)
  101. {
  102.     int        i;
  103.     
  104.     for (i=1 ; i<MAX_HANDLES ; i++)
  105.         if (!sys_handles[i])
  106.             return i;
  107.     Sys_Error ("out of handles");
  108.     return -1;
  109. }
  110.  
  111. /*
  112. ================
  113. filelength
  114. ================
  115. */
  116. int filelength (FILE *f)
  117. {
  118.     int        pos;
  119.     int        end;
  120.     int        t;
  121.  
  122.     t = VID_ForceUnlockedAndReturnState ();
  123.  
  124.     pos = ftell (f);
  125.     fseek (f, 0, SEEK_END);
  126.     end = ftell (f);
  127.     fseek (f, pos, SEEK_SET);
  128.  
  129.     VID_ForceLockState (t);
  130.  
  131.     return end;
  132. }
  133.  
  134. int Sys_FileOpenRead (char *path, int *hndl)
  135. {
  136.     FILE    *f;
  137.     int        i, retval;
  138.     int        t;
  139.  
  140.     t = VID_ForceUnlockedAndReturnState ();
  141.  
  142.     i = findhandle ();
  143.  
  144.     f = fopen(path, "rb");
  145.  
  146.     if (!f)
  147.     {
  148.         *hndl = -1;
  149.         retval = -1;
  150.     }
  151.     else
  152.     {
  153.         sys_handles[i] = f;
  154.         *hndl = i;
  155.         retval = filelength(f);
  156.     }
  157.  
  158.     VID_ForceLockState (t);
  159.  
  160.     return retval;
  161. }
  162.  
  163. int Sys_FileOpenWrite (char *path)
  164. {
  165.     FILE    *f;
  166.     int        i;
  167.     int        t;
  168.  
  169.     t = VID_ForceUnlockedAndReturnState ();
  170.     
  171.     i = findhandle ();
  172.  
  173.     f = fopen(path, "wb");
  174.     if (!f)
  175.         Sys_Error ("Error opening %s: %s", path,strerror(errno));
  176.     sys_handles[i] = f;
  177.     
  178.     VID_ForceLockState (t);
  179.  
  180.     return i;
  181. }
  182.  
  183. void Sys_FileClose (int handle)
  184. {
  185.     int        t;
  186.  
  187.     t = VID_ForceUnlockedAndReturnState ();
  188.     fclose (sys_handles[handle]);
  189.     sys_handles[handle] = NULL;
  190.     VID_ForceLockState (t);
  191. }
  192.  
  193. void Sys_FileSeek (int handle, int position)
  194. {
  195.     int        t;
  196.  
  197.     t = VID_ForceUnlockedAndReturnState ();
  198.     fseek (sys_handles[handle], position, SEEK_SET);
  199.     VID_ForceLockState (t);
  200. }
  201.  
  202. int Sys_FileRead (int handle, void *dest, int count)
  203. {
  204.     int        t, x;
  205.  
  206.     t = VID_ForceUnlockedAndReturnState ();
  207.     x = fread (dest, 1, count, sys_handles[handle]);
  208.     VID_ForceLockState (t);
  209.     return x;
  210. }
  211.  
  212. int Sys_FileWrite (int handle, void *data, int count)
  213. {
  214.     int        t, x;
  215.  
  216.     t = VID_ForceUnlockedAndReturnState ();
  217.     x = fwrite (data, 1, count, sys_handles[handle]);
  218.     VID_ForceLockState (t);
  219.     return x;
  220. }
  221.  
  222. int    Sys_FileTime (char *path)
  223. {
  224.     FILE    *f;
  225.     int        t, retval;
  226.  
  227.     t = VID_ForceUnlockedAndReturnState ();
  228.     
  229.     f = fopen(path, "rb");
  230.  
  231.     if (f)
  232.     {
  233.         fclose(f);
  234.         retval = 1;
  235.     }
  236.     else
  237.     {
  238.         retval = -1;
  239.     }
  240.     
  241.     VID_ForceLockState (t);
  242.     return retval;
  243. }
  244.  
  245. void Sys_mkdir (char *path)
  246. {
  247.     _mkdir (path);
  248. }
  249.  
  250.  
  251. /*
  252. ===============================================================================
  253.  
  254. SYSTEM IO
  255.  
  256. ===============================================================================
  257. */
  258.  
  259. /*
  260. ================
  261. Sys_MakeCodeWriteable
  262. ================
  263. */
  264. void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
  265. {
  266.     DWORD  flOldProtect;
  267.  
  268.     if (!VirtualProtect((LPVOID)startaddr, length, PAGE_READWRITE, &flOldProtect))
  269.            Sys_Error("Protection change failed\n");
  270. }
  271.  
  272.  
  273. #ifndef _M_IX86
  274.  
  275. void Sys_SetFPCW (void)
  276. {
  277. }
  278.  
  279. void Sys_PushFPCW_SetHigh (void)
  280. {
  281. }
  282.  
  283. void Sys_PopFPCW (void)
  284. {
  285. }
  286.  
  287. void MaskExceptions (void)
  288. {
  289. }
  290.  
  291. #endif
  292.  
  293. /*
  294. ================
  295. Sys_Init
  296. ================
  297. */
  298. void Sys_Init (void)
  299. {
  300.     LARGE_INTEGER    PerformanceFreq;
  301.     unsigned int    lowpart, highpart;
  302.     OSVERSIONINFO    vinfo;
  303.  
  304.     MaskExceptions ();
  305.     Sys_SetFPCW ();
  306.  
  307.     if (!QueryPerformanceFrequency (&PerformanceFreq))
  308.         Sys_Error ("No hardware timer available");
  309.  
  310. // get 32 out of the 64 time bits such that we have around
  311. // 1 microsecond resolution
  312.     lowpart = (unsigned int)PerformanceFreq.LowPart;
  313.     highpart = (unsigned int)PerformanceFreq.HighPart;
  314.     lowshift = 0;
  315.  
  316.     while (highpart || (lowpart > 2000000.0))
  317.     {
  318.         lowshift++;
  319.         lowpart >>= 1;
  320.         lowpart |= (highpart & 1) << 31;
  321.         highpart >>= 1;
  322.     }
  323.  
  324.     pfreq = 1.0 / (double)lowpart;
  325.  
  326.     Sys_InitFloatTime ();
  327.  
  328.     vinfo.dwOSVersionInfoSize = sizeof(vinfo);
  329.  
  330.     if (!GetVersionEx (&vinfo))
  331.         Sys_Error ("Couldn't get OS info");
  332.  
  333.     if ((vinfo.dwMajorVersion < 4) ||
  334.         (vinfo.dwPlatformId == VER_PLATFORM_WIN32s))
  335.     {
  336.         Sys_Error ("WinQuake requires at least Win95 or NT 4.0");
  337.     }
  338.  
  339.     if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
  340.         WinNT = true;
  341.     else
  342.         WinNT = false;
  343. }
  344.  
  345.  
  346. void Sys_Error (char *error, ...)
  347. {
  348.     va_list        argptr;
  349.     char        text[1024], text2[1024];
  350.     char        *text3 = "Press Enter to exit\n";
  351.     char        *text4 = "***********************************\n";
  352.     char        *text5 = "\n";
  353.     DWORD        dummy;
  354.     double        starttime;
  355.     static int    in_sys_error0 = 0;
  356.     static int    in_sys_error1 = 0;
  357.     static int    in_sys_error2 = 0;
  358.     static int    in_sys_error3 = 0;
  359.  
  360.     if (!in_sys_error3)
  361.     {
  362.         in_sys_error3 = 1;
  363.         VID_ForceUnlockedAndReturnState ();
  364.     }
  365.  
  366.     va_start (argptr, error);
  367.     vsprintf (text, error, argptr);
  368.     va_end (argptr);
  369.  
  370.     if (isDedicated)
  371.     {
  372.         va_start (argptr, error);
  373.         vsprintf (text, error, argptr);
  374.         va_end (argptr);
  375.  
  376.         sprintf (text2, "ERROR: %s\n", text);
  377.         WriteFile (houtput, text5, strlen (text5), &dummy, NULL);
  378.         WriteFile (houtput, text4, strlen (text4), &dummy, NULL);
  379.         WriteFile (houtput, text2, strlen (text2), &dummy, NULL);
  380.         WriteFile (houtput, text3, strlen (text3), &dummy, NULL);
  381.         WriteFile (houtput, text4, strlen (text4), &dummy, NULL);
  382.  
  383.  
  384.         starttime = Sys_FloatTime ();
  385.         sc_return_on_enter = true;    // so Enter will get us out of here
  386.  
  387.         while (!Sys_ConsoleInput () &&
  388.                 ((Sys_FloatTime () - starttime) < CONSOLE_ERROR_TIMEOUT))
  389.         {
  390.         }
  391.     }
  392.     else
  393.     {
  394.     // switch to windowed so the message box is visible, unless we already
  395.     // tried that and failed
  396.         if (!in_sys_error0)
  397.         {
  398.             in_sys_error0 = 1;
  399.             VID_SetDefaultMode ();
  400.             MessageBox(NULL, text, "Quake Error",
  401.                        MB_OK | MB_SETFOREGROUND | MB_ICONSTOP);
  402.         }
  403.         else
  404.         {
  405.             MessageBox(NULL, text, "Double Quake Error",
  406.                        MB_OK | MB_SETFOREGROUND | MB_ICONSTOP);
  407.         }
  408.     }
  409.  
  410.     if (!in_sys_error1)
  411.     {
  412.         in_sys_error1 = 1;
  413.         Host_Shutdown ();
  414.     }
  415.  
  416. // shut down QHOST hooks if necessary
  417.     if (!in_sys_error2)
  418.     {
  419.         in_sys_error2 = 1;
  420.         DeinitConProc ();
  421.     }
  422.  
  423.     exit (1);
  424. }
  425.  
  426. void Sys_Printf (char *fmt, ...)
  427. {
  428.     va_list        argptr;
  429.     char        text[1024];
  430.     DWORD        dummy;
  431.     
  432.     if (isDedicated)
  433.     {
  434.         va_start (argptr,fmt);
  435.         vsprintf (text, fmt, argptr);
  436.         va_end (argptr);
  437.  
  438.         WriteFile(houtput, text, strlen (text), &dummy, NULL);    
  439.     }
  440. }
  441.  
  442. void Sys_Quit (void)
  443. {
  444.  
  445.     VID_ForceUnlockedAndReturnState ();
  446.  
  447.     Host_Shutdown();
  448.  
  449.     if (tevent)
  450.         CloseHandle (tevent);
  451.  
  452.     if (isDedicated)
  453.         FreeConsole ();
  454.  
  455. // shut down QHOST hooks if necessary
  456.     DeinitConProc ();
  457.  
  458.     exit (0);
  459. }
  460.  
  461.  
  462. /*
  463. ================
  464. Sys_FloatTime
  465. ================
  466. */
  467. double Sys_FloatTime (void)
  468. {
  469.     static int            sametimecount;
  470.     static unsigned int    oldtime;
  471.     static int            first = 1;
  472.     LARGE_INTEGER        PerformanceCount;
  473.     unsigned int        temp, t2;
  474.     double                time;
  475.  
  476.     Sys_PushFPCW_SetHigh ();
  477.  
  478.     QueryPerformanceCounter (&PerformanceCount);
  479.  
  480.     temp = ((unsigned int)PerformanceCount.LowPart >> lowshift) |
  481.            ((unsigned int)PerformanceCount.HighPart << (32 - lowshift));
  482.  
  483.     if (first)
  484.     {
  485.         oldtime = temp;
  486.         first = 0;
  487.     }
  488.     else
  489.     {
  490.     // check for turnover or backward time
  491.         if ((temp <= oldtime) && ((oldtime - temp) < 0x10000000))
  492.         {
  493.             oldtime = temp;    // so we can't get stuck
  494.         }
  495.         else
  496.         {
  497.             t2 = temp - oldtime;
  498.  
  499.             time = (double)t2 * pfreq;
  500.             oldtime = temp;
  501.  
  502.             curtime += time;
  503.  
  504.             if (curtime == lastcurtime)
  505.             {
  506.                 sametimecount++;
  507.  
  508.                 if (sametimecount > 100000)
  509.                 {
  510.                     curtime += 1.0;
  511.                     sametimecount = 0;
  512.                 }
  513.             }
  514.             else
  515.             {
  516.                 sametimecount = 0;
  517.             }
  518.  
  519.             lastcurtime = curtime;
  520.         }
  521.     }
  522.  
  523.     Sys_PopFPCW ();
  524.  
  525.     return curtime;
  526. }
  527.  
  528.  
  529. /*
  530. ================
  531. Sys_InitFloatTime
  532. ================
  533. */
  534. void Sys_InitFloatTime (void)
  535. {
  536.     int        j;
  537.  
  538.     Sys_FloatTime ();
  539.  
  540.     j = COM_CheckParm("-starttime");
  541.  
  542.     if (j)
  543.     {
  544.         curtime = (double) (Q_atof(com_argv[j+1]));
  545.     }
  546.     else
  547.     {
  548.         curtime = 0.0;
  549.     }
  550.  
  551.     lastcurtime = curtime;
  552. }
  553.  
  554.  
  555. char *Sys_ConsoleInput (void)
  556. {
  557.     static char    text[256];
  558.     static int        len;
  559.     INPUT_RECORD    recs[1024];
  560.     int        count;
  561.     int        i, dummy;
  562.     int        ch, numread, numevents;
  563.  
  564.     if (!isDedicated)
  565.         return NULL;
  566.  
  567.  
  568.     for ( ;; )
  569.     {
  570.         if (!GetNumberOfConsoleInputEvents (hinput, &numevents))
  571.             Sys_Error ("Error getting # of console events");
  572.  
  573.         if (numevents <= 0)
  574.             break;
  575.  
  576.         if (!ReadConsoleInput(hinput, recs, 1, &numread))
  577.             Sys_Error ("Error reading console input");
  578.  
  579.         if (numread != 1)
  580.             Sys_Error ("Couldn't read console input");
  581.  
  582.         if (recs[0].EventType == KEY_EVENT)
  583.         {
  584.             if (!recs[0].Event.KeyEvent.bKeyDown)
  585.             {
  586.                 ch = recs[0].Event.KeyEvent.uChar.AsciiChar;
  587.  
  588.                 switch (ch)
  589.                 {
  590.                     case '\r':
  591.                         WriteFile(houtput, "\r\n", 2, &dummy, NULL);    
  592.  
  593.                         if (len)
  594.                         {
  595.                             text[len] = 0;
  596.                             len = 0;
  597.                             return text;
  598.                         }
  599.                         else if (sc_return_on_enter)
  600.                         {
  601.                         // special case to allow exiting from the error handler on Enter
  602.                             text[0] = '\r';
  603.                             len = 0;
  604.                             return text;
  605.                         }
  606.  
  607.                         break;
  608.  
  609.                     case '\b':
  610.                         WriteFile(houtput, "\b \b", 3, &dummy, NULL);    
  611.                         if (len)
  612.                         {
  613.                             len--;
  614.                         }
  615.                         break;
  616.  
  617.                     default:
  618.                         if (ch >= ' ')
  619.                         {
  620.                             WriteFile(houtput, &ch, 1, &dummy, NULL);    
  621.                             text[len] = ch;
  622.                             len = (len + 1) & 0xff;
  623.                         }
  624.  
  625.                         break;
  626.  
  627.                 }
  628.             }
  629.         }
  630.     }
  631.  
  632.     return NULL;
  633. }
  634.  
  635. void Sys_Sleep (void)
  636. {
  637.     Sleep (1);
  638. }
  639.  
  640.  
  641. void Sys_SendKeyEvents (void)
  642. {
  643.     MSG        msg;
  644.  
  645.     while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
  646.     {
  647.     // we always update if there are any event, even if we're paused
  648.         scr_skipupdate = 0;
  649.  
  650.         if (!GetMessage (&msg, NULL, 0, 0))
  651.             Sys_Quit ();
  652.  
  653.           TranslateMessage (&msg);
  654.           DispatchMessage (&msg);
  655.     }
  656. }
  657.  
  658.  
  659. /*
  660. ==============================================================================
  661.  
  662.  WINDOWS CRAP
  663.  
  664. ==============================================================================
  665. */
  666.  
  667.  
  668. /*
  669. ==================
  670. WinMain
  671. ==================
  672. */
  673. void SleepUntilInput (int time)
  674. {
  675.  
  676.     MsgWaitForMultipleObjects(1, &tevent, FALSE, time, QS_ALLINPUT);
  677. }
  678.  
  679.  
  680. /*
  681. ==================
  682. WinMain
  683. ==================
  684. */
  685. HINSTANCE    global_hInstance;
  686. int            global_nCmdShow;
  687. char        *argv[MAX_NUM_ARGVS];
  688. static char    *empty_string = "";
  689. HWND        hwnd_dialog;
  690.  
  691.  
  692. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  693. {
  694.     MSG                msg;
  695.     quakeparms_t    parms;
  696.     double            time, oldtime, newtime;
  697.     MEMORYSTATUS    lpBuffer;
  698.     static    char    cwd[1024];
  699.     int                t;
  700.     RECT            rect;
  701.  
  702.     /* previous instances do not exist in Win32 */
  703.     if (hPrevInstance)
  704.         return 0;
  705.  
  706.     global_hInstance = hInstance;
  707.     global_nCmdShow = nCmdShow;
  708.  
  709.     lpBuffer.dwLength = sizeof(MEMORYSTATUS);
  710.     GlobalMemoryStatus (&lpBuffer);
  711.  
  712.     if (!GetCurrentDirectory (sizeof(cwd), cwd))
  713.         Sys_Error ("Couldn't determine current directory");
  714.  
  715.     if (cwd[Q_strlen(cwd)-1] == '/')
  716.         cwd[Q_strlen(cwd)-1] = 0;
  717.  
  718.     parms.basedir = cwd;
  719.     parms.cachedir = NULL;
  720.  
  721.     parms.argc = 1;
  722.     argv[0] = empty_string;
  723.  
  724.     while (*lpCmdLine && (parms.argc < MAX_NUM_ARGVS))
  725.     {
  726.         while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126)))
  727.             lpCmdLine++;
  728.  
  729.         if (*lpCmdLine)
  730.         {
  731.             argv[parms.argc] = lpCmdLine;
  732.             parms.argc++;
  733.  
  734.             while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126)))
  735.                 lpCmdLine++;
  736.  
  737.             if (*lpCmdLine)
  738.             {
  739.                 *lpCmdLine = 0;
  740.                 lpCmdLine++;
  741.             }
  742.             
  743.         }
  744.     }
  745.  
  746.     parms.argv = argv;
  747.  
  748.     COM_InitArgv (parms.argc, parms.argv);
  749.  
  750.     parms.argc = com_argc;
  751.     parms.argv = com_argv;
  752.  
  753.     isDedicated = (COM_CheckParm ("-dedicated") != 0);
  754.  
  755.     if (!isDedicated)
  756.     {
  757.         hwnd_dialog = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, NULL);
  758.  
  759.         if (hwnd_dialog)
  760.         {
  761.             if (GetWindowRect (hwnd_dialog, &rect))
  762.             {
  763.                 if (rect.left > (rect.top * 2))
  764.                 {
  765.                     SetWindowPos (hwnd_dialog, 0,
  766.                         (rect.left / 2) - ((rect.right - rect.left) / 2),
  767.                         rect.top, 0, 0,
  768.                         SWP_NOZORDER | SWP_NOSIZE);
  769.                 }
  770.             }
  771.  
  772.             ShowWindow (hwnd_dialog, SW_SHOWDEFAULT);
  773.             UpdateWindow (hwnd_dialog);
  774.             SetForegroundWindow (hwnd_dialog);
  775.         }
  776.     }
  777.  
  778. // take the greater of all the available memory or half the total memory,
  779. // but at least 8 Mb and no more than 16 Mb, unless they explicitly
  780. // request otherwise
  781.     parms.memsize = lpBuffer.dwAvailPhys;
  782.  
  783.     if (parms.memsize < MINIMUM_WIN_MEMORY)
  784.         parms.memsize = MINIMUM_WIN_MEMORY;
  785.  
  786.     if (parms.memsize < (lpBuffer.dwTotalPhys >> 1))
  787.         parms.memsize = lpBuffer.dwTotalPhys >> 1;
  788.  
  789.     if (parms.memsize > MAXIMUM_WIN_MEMORY)
  790.         parms.memsize = MAXIMUM_WIN_MEMORY;
  791.  
  792.     if (COM_CheckParm ("-heapsize"))
  793.     {
  794.         t = COM_CheckParm("-heapsize") + 1;
  795.  
  796.         if (t < com_argc)
  797.             parms.memsize = Q_atoi (com_argv[t]) * 1024;
  798.     }
  799.  
  800.     parms.membase = malloc (parms.memsize);
  801.  
  802.     if (!parms.membase)
  803.         Sys_Error ("Not enough memory free; check disk space\n");
  804.  
  805.     Sys_PageIn (parms.membase, parms.memsize);
  806.  
  807.     tevent = CreateEvent(NULL, FALSE, FALSE, NULL);
  808.  
  809.     if (!tevent)
  810.         Sys_Error ("Couldn't create event");
  811.  
  812.     if (isDedicated)
  813.     {
  814.         if (!AllocConsole ())
  815.         {
  816.             Sys_Error ("Couldn't create dedicated server console");
  817.         }
  818.  
  819.         hinput = GetStdHandle (STD_INPUT_HANDLE);
  820.         houtput = GetStdHandle (STD_OUTPUT_HANDLE);
  821.  
  822.     // give QHOST a chance to hook into the console
  823.         if ((t = COM_CheckParm ("-HFILE")) > 0)
  824.         {
  825.             if (t < com_argc)
  826.                 hFile = (HANDLE)Q_atoi (com_argv[t+1]);
  827.         }
  828.             
  829.         if ((t = COM_CheckParm ("-HPARENT")) > 0)
  830.         {
  831.             if (t < com_argc)
  832.                 heventParent = (HANDLE)Q_atoi (com_argv[t+1]);
  833.         }
  834.             
  835.         if ((t = COM_CheckParm ("-HCHILD")) > 0)
  836.         {
  837.             if (t < com_argc)
  838.                 heventChild = (HANDLE)Q_atoi (com_argv[t+1]);
  839.         }
  840.  
  841.         InitConProc (hFile, heventParent, heventChild);
  842.     }
  843.  
  844.     Sys_Init ();
  845.  
  846. // because sound is off until we become active
  847.     S_BlockSound ();
  848.  
  849.     Sys_Printf ("Host_Init\n");
  850.     Host_Init (&parms);
  851.  
  852.     oldtime = Sys_FloatTime ();
  853.  
  854.     /* main window message loop */
  855.     while (1)
  856.     {
  857.         if (isDedicated)
  858.         {
  859.             newtime = Sys_FloatTime ();
  860.             time = newtime - oldtime;
  861.  
  862.             while (time < sys_ticrate.value )
  863.             {
  864.                 Sys_Sleep();
  865.                 newtime = Sys_FloatTime ();
  866.                 time = newtime - oldtime;
  867.             }
  868.         }
  869.         else
  870.         {
  871.         // yield the CPU for a little while when paused, minimized, or not the focus
  872.             if ((cl.paused && (!ActiveApp && !DDActive)) || Minimized || block_drawing)
  873.             {
  874.                 SleepUntilInput (PAUSE_SLEEP);
  875.                 scr_skipupdate = 1;        // no point in bothering to draw
  876.             }
  877.             else if (!ActiveApp && !DDActive)
  878.             {
  879.                 SleepUntilInput (NOT_FOCUS_SLEEP);
  880.             }
  881.  
  882.             newtime = Sys_FloatTime ();
  883.             time = newtime - oldtime;
  884.         }
  885.  
  886.         Host_Frame (time);
  887.         oldtime = newtime;
  888.     }
  889.  
  890.     /* return success of application */
  891.     return TRUE;
  892. }
  893.  
  894.